package com.roger.myHome.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.roger.myHome.entity.Course;
import com.roger.myHome.entity.CourseQTO;
import com.roger.myHome.entity.Dept;
import com.roger.myHome.importDemo.UserDataListener;
import com.roger.myHome.importDemo.UserImportDTO;
import com.roger.myHome.mapper.CommonMapper;
import com.roger.myHome.mapper.CourseMapper;
import com.roger.myHome.mapper.DeptMapper;
import com.roger.myHome.mapper.TicketMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/excel")
@Slf4j
public class ExcelImportController {

    @Autowired
    private UserDataListener userDataListener;

    @Resource
    private CourseMapper courseMapper;

    @Resource
    private CommonMapper commonMapper;

    @Resource
    private DeptMapper deptMapper;

    @GetMapping("/import")
    public String importExcel() throws IOException {
        //EasyExcel.read(file.getInputStream(), UserImportDTO.class, userDataListener).sheet().doRead();
        //InputStream inputStream = getInputStreamByUrl("D:\\test.xlsx");
        //EasyExcel.read(inputStream, UserImportDTO.class, userDataListener).sheet().doRead();


        //common();
        customized();
        //insert();
        //deptList();
        return "";
    }

    private void insert() {
        long begin = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        // 提交两个任务到线程池
        Future<String> future1 = executorService.submit(() -> {
            // 模拟耗时任务
            for (int i = 0; i < 10000; i++) {
                String name = UUID.randomUUID().toString();
                commonMapper.insertSql("insert into course(course_name) values('"+name+"')");
            }
            return "success";
        });

        Future<String> future2 = executorService.submit(() -> {
            // 模拟耗时任务
            for (int i = 0; i < 20000; i++) {
                String name = UUID.randomUUID().toString();
                commonMapper.insertSql("insert into course(course_name) values('"+name+"')");
            }
            return "success";
        });


        try {
            String result1 = future1.get();


            // 获取任务2的结果，如果任务尚未完成，则会阻塞等待
            String result2 = future2.get();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown();
        }

    }

    private void common () {
        long startTime = System.currentTimeMillis();
        List<Course> list = courseMapper.totalPage();
        log.info("导出耗时/ms:"+((System.currentTimeMillis()-startTime)/1000)+",导出数据总条数："+ list.size());
    }

    private void customized() {
        long startTime = System.currentTimeMillis();

        //每个页的记录条数
        Integer pageSize = 50;

        //总记录条数
        Integer total = courseMapper.totalSize();

        //计算出总页数，也就是线程数
        Integer pages = 0;
        if ((total % pageSize) == 0) {
            pages = total / pageSize;
        } else {
            pages = (total / pageSize) + 1;
        }

        log.info("总页数:{}", pages);
        //大数据量时，进行分页查询写入
        ExecutorService taskExecutor = Executors.newCachedThreadPool();
        final CountDownLatch latch = new CountDownLatch(pages);//用于判断所有的线程是否结束

        List<List<Course>> resultList = Collections.synchronizedList(new ArrayList<>());
        log.info("共{}页", pages);
        for (int m = 0; m < pages; m++) {
            final int n = m;//内部类里m不能直接用,所以赋值给n

            Runnable run = new Runnable() {
                public void run() {
                    try {
                        CourseQTO courseQTO = new CourseQTO();
                        courseQTO.setPageSize(pageSize);
                        courseQTO.setCurrPage(n + 1);

                        List<Course> pageList = courseMapper.page(courseQTO);
                        log.info("执行第:{}页,参数：{}" , (n+1) , courseQTO);
                        resultList.add(pageList);

                    } finally {
                        latch.countDown(); //每次调用CountDown()，计数减1
                    }
                }
            };
            taskExecutor.execute(run);
        }

        try {
            //等待所有线程执行完毕
            latch.await();//主程序执行到await()函数会阻塞等待线程的执行，直到计数为0
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        taskExecutor.shutdown();//关闭线程池
        //所有线程执行完毕,执行主线程

        log.info("导出耗时/ms:"+((System.currentTimeMillis()-startTime)/1000)+",导出数据总条数："+ resultList.size());
    }

    public static InputStream getInputStreamByUrl(String filePath){
        InputStream inputStream =  null;
        try {
            inputStream = new FileInputStream(filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return inputStream;
    }

    public String deptList() {
        List<Dept> dbList = deptMapper.selectAll();

        // 2. 放到 Map
        Map<Integer, Dept> map = dbList.stream()
                .collect(Collectors.toMap(Dept::getId, n -> n));

        List<Dept> parentList = findParents(map, 263);
        System.out.println("parent==================");
        Integer parentId = null;
        for (Dept dept : parentList) {
            if (dept.getParentId() == 10) {
                parentId = dept.getId();
            }
        }

        System.out.println(parentId);
        return parentId + "";
    }

    //根据id递归查父亲结点
    public static List<Dept> findParents(Map<Integer, Dept> allNodeMap, Integer childId) {
        List<Dept> path = new ArrayList<>();
        collectParent(allNodeMap, childId, path);
        return path;
    }

    private static void collectParent(Map<Integer, Dept> map, Integer id, List<Dept> path) {
        if (id == null) {
            return;
        }
        Dept node = map.get(id);
        if (node == null) {
            return;
        }

        // 先把自己放进去
        path.add(node);
        // 再递归父亲
        collectParent(map, node.getParentId(), path);
    }

    public static void main(String[] args) {
        System.out.println(1234 / 100);
    }
}
